#include "stdafx.h"
#include "solovay_strassen_test.h"

using namespace std;

//#define SYMBOLS
//#define TEST
#define PRINT
int main()
{
#ifdef SYMBOLS
	cout<<uint128::jacobi_symbol(6,7)+'2'<<'\n';
	return 0;
#endif
	srand(int(time(NULL)));
#ifdef TEST
	//  tests 
	ostream &str=cout;
	const int N=20;
	double t=0.5;
	const int PRIME=10,COMP=20;
	uint128 prime_always[PRIME]={8363,1657,9781,9049,6673,
		                           1867,1901,1303,5479,8111};
	uint128 rather_composite[COMP]={1105,2465,10585,1729,2821,
		                         8911,6601,2821,15841,52633,
		                         625,791,3871,2007,6785,
		                         1969,5705,3445,6105,3621};
	double res_prime[PRIME],res_comp[COMP];
	for(int j=0;j<PRIME;++j) res_prime[j]=0;for(int j=0;j<COMP;++j) res_comp[j]=0;
	for(int i=0;i<N;++i)
	{
		str<<'.';
		for(int j=0;j<PRIME;++j) if(probably_prime(prime_always[j],t)) ++res_prime[j];
		for(int j=0;j<COMP;++j)	if(probably_prime(rather_composite[j],t)) ++res_comp[j];
	}
	str<<"\n always prime:\n";for(int j=0;j<PRIME;++j) str<<(res_prime[j]/=N)<<'\t';
	str<<"\n rather composite:\n";for(int j=0;j<COMP;++j) str<<(res_comp[j]/=N)<<'\t';
	str<<endl;
	//  end of tests  
#else /* TEST */
	const unsigned int N=10;

	ofstream outfile("report.txt");
	ostream &str=
#ifdef PRINT
		outfile;
#else /* PRINT */
		cout;
#endif /* PRINT */
	const unsigned int WIDTH=62;
	str<<setw(WIDTH)<<setfill('-')<<'\n';
	str<<"| # |                prime number                | attempts |\n";
	str<<setw(WIDTH)<<setfill('-')<<'\n';
	str<<setfill(' ');
	for(int i=0;i<N;++i)
	{
#ifdef PRINT
		cout<<i+1<<" number\n";
#endif /* PRINT */
		uint128 n;
		unsigned int attempts=0;
		do
		{
			n=uint128::random();
			if(n._h>>63==1) 
			{
				++attempts;
#ifdef PRINT
				cout<<attempts<<" attempt is "<<n<<"\n";
#endif /* PRINT */
			}
			else
			{
#ifdef PRINT
				cout<<attempts+1<<" attempt is "<<n<<" < 128 bits"<<"\n";
#endif /* PRINT */
				continue;
			}
		}
		while(!probably_prime(n));
#ifdef PRINT
		cout<<i+1<<" prime number is found: "<<n<<" for "<<attempts<<" attempts!\n\n";
#endif /* PRINT */
		str<<"|"<<setw(3)<<i+1
			<<"| "<<n
			<<" |"<<setw(10)<<attempts
		    <<"|\n";
	}
	str<<setw(WIDTH)<<setfill('-')<<'\n';
	outfile.close();
	/*
    n=2^128/ln(2^128)-2^127/ln(2^127)=2^127/ln(2)*(1/64-1/127)
	p=n/N=2^127/ln(2)*(1/64-1/127)/2^127=(1/64-1/127)/ln(2)~=0,011
	k>=log(1-p) 0.1~=205
	*/
#endif /* TEST */
	return 0;
}